package com.jrx.anytxn.atom.service.impl;

import com.jrx.anytxn.atom.service.IAfterHandleService;
import com.jrx.anytxn.common.annotation.CollectionModel;
import com.jrx.anytxn.common.annotation.MethodType;
import com.jrx.anytxn.common.annotation.Model;
import com.jrx.anytxn.common.constant.CommonContants;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 所有继承BaseBatchAccoutHandle的处理类处理自身业务后的通用处理
 * @program: anytxn-cf-parent
 * @description:
 * @author: xiaoyu.jing
 * @date: 2020-09-09 11:30
 **/
@Service
public class CommonAfterHandleService<E> implements IAfterHandleService<E> {

    private static final Map<String, Method[]> methodMapCache = new ConcurrentHashMap<>();

    @Override
    public void afterHandle(Collection<E> list) throws Exception {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        //轮询处理业务处理后的返回对象
        for (E e : list) {
            this.afterHandle(e);
        }
    }


    private void afterHandle(Object obj) throws Exception {
        if(null == obj){
            return;
        }

        //判断对象是否为最终处理对象，例如UpdateUncastIntrHandle，需要对返回的AmLoanAccountInfo进行处理
        if(obj.getClass().isAnnotationPresent(Model.class)){
            MethodType methodType = obj.getClass().getAnnotation(MethodType.class);
            this.dealMethodType(methodType,obj);
            return;
        }

        //从缓存终获取对象的所有方法，如果没有则通过反射获取
        Method[] methods;
        if(methodMapCache.containsKey(obj.getClass().getName())){
            methods = methodMapCache.get(obj.getClass().getName());
        }else{
            methods = ReflectionUtils.getAllDeclaredMethods(obj.getClass());
            methodMapCache.put(obj.getClass().getName(),methods);
        }

        //轮询方法根据方法标记的注解进行处理
        for (Method method : methods) {
            method.setAccessible(true);
            //如果方法返回一个对象继续递归处理
            if (method.isAnnotationPresent(Model.class)) {
                Object modle = method.invoke(obj);
                this.afterHandle(modle);
                continue;
            }

            //如果对象返回一个List 继续迭代处理
            if (method.isAnnotationPresent(CollectionModel.class)) {
                Collection collection = (Collection) method.invoke(obj);
                this.afterHandle(collection);
                continue;
            }

            //如果没有标记方法则跳过
            if (!method.isAnnotationPresent(MethodType.class)) {
                continue;
            }

            //真正处理
            Object data = method.invoke(obj);
            MethodType methodType = method.getAnnotation(MethodType.class);
            this.dealMethodType(methodType,data);
        }
    }

    private void dealMethodType(MethodType methodType,Object data) throws Exception {
        if(null == data){
            return;
        }

        //如果标记为需要更新的对象
        if ( CommonContants.METHOD_TYPE_UPDATE.equals(methodType.value())) {
            if (data instanceof List) {
                CustBatchHelper.dealUpdateList((List)data);
            } else {
                CustBatchHelper.dealUpdateList(Collections.singletonList(data));
            }
        //如果标记为需要保存的对象
        } else if (CommonContants.METHOD_TYPE_SAVE.equals(methodType.value())) {
            if (data instanceof List) {
                CustBatchHelper.dealSaveList( (List)data);
            }else{
                CustBatchHelper.dealSaveList(Collections.singletonList(data));
            }

        }
    }
}
